/*
 * Project: Digital Wristwatch
 * Author: Zak Kemble, contact@zakkemble.co.uk
 * Copyright: (C) 2013 by Zak Kemble
 * License: GNU GPL v3 (see License.txt)
 * Web: http://blog.zakkemble.co.uk/diy-digital-wristwatch/
 */

// Buzzer
// Timer1 is used for buzzing

#include <avr/io.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "common.h"
#include "devices/buzzer.h"
#include "millis/millis.h"
#include "watchconfig.h"
#include "pwrmgr.h"

static byte buzzLen;
static millis8_t startTime;

void buzzer_init()
{

}

// Non-blocking buzz
void buzzer_buzz(byte len, tone_t tone, vol_t volType)
{
	// Workout volume
	uint ocr;
	byte vol;

	switch(volType)
	{
		case VOL_UI:
			vol = watchConfig.volUI;
			break;
		case VOL_ALARM:
			vol = watchConfig.volAlarm;
			break;
		default:
			vol = 2;
			break;
	}

	switch(vol)
	{
		case 1:
			ocr = (tone * 2) - (tone / 16);
			break;
		case 2:
			ocr = (tone * 2) - (tone / 8);
			break;
		case 3:
			ocr = (tone * 2) - (tone / 4);
			break;
		default:
			return;
	}

	buzzLen = len;
	startTime = millis();
	
	TCD1.PER = tone * 2;
	TCD1.CCB = ocr;
	//TCD1.CTRLC = 0x02;//Match cmp when timer turn off ( Turn off buzzing MOS)
	TCD1.CTRLB = 0x23;//CCBEN, Single-slope PWM
	TCD1.CTRLA = 0x04;//DIV8, 2MHz

	// Tell power manager that we are busy buzzing
	pwrmgr_setState(PWR_ACTIVE_BUZZER, PWR_STATE_IDLE);
}

// Are we buzzing?
bool buzzer_buzzing()
{
	return buzzLen;
}

// See if its time to stop buzzing
void buzzer_update()
{
	millis8_t elapsed = (millis8_t)(millis() - startTime);
	if(buzzLen && (elapsed >= buzzLen))
	{
		while(!testbit(PORT_BEEP_IN, PIN_BEEPER));//waiting for pin high
		while(testbit(PORT_BEEP_IN, PIN_BEEPER));//waiting for pin low
		TCD1.CTRLA = 0x00;//OFF
		buzzLen = 0;
		
		pwrmgr_setState(PWR_ACTIVE_BUZZER, PWR_STATE_NONE);
	}
}

